home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / processes / howtohideyourapp / hidecalls.c next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  5.6 KB  |  171 lines

  1. /*    File:        HideCalls.c
  2.     
  3.     Description: 
  4.              This sample illustrates how the SetHideOnSwitch and GetHideOnSwitch
  5.             routines can be used to hide an application.  These routines were first
  6.             documented in Technote TN1102, "Mac OS 8".  On the world wide
  7.             web, documentation for these routines can be found at the address:
  8.             
  9.             http://developer.apple.com/technotes/tn/tn1102.html#processmgr
  10.             
  11.             This file contains PowerPC routines that can be used to hide an
  12.             applicaton.
  13.  
  14.     Copyright: 
  15.             Copyright © 1999 by Apple Computer, Inc.
  16.             All rights reserved.
  17.     
  18.     Disclaimer:
  19.             You may incorporate this sample code into your applications without
  20.             restriction, though the sample code has been provided "AS IS" and the
  21.             responsibility for its operation is 100% yours.  However, what you are
  22.             not permitted to do is to redistribute the source as "DSC Sample Code"
  23.             after having made changes. If you're going to re-distribute the source,
  24.             we require that you make it clear in the source that the code was
  25.             descended from Apple Sample Code, but that you've made changes.
  26.     
  27.     Change History (most recent first):
  28.             12/6/1999 created
  29. */
  30.  
  31.  
  32. #include "HideCalls.h"
  33. #include <MixedMode.h>
  34. #include <Traps.h>
  35. #include <Errors.h>
  36. #include <Gestalt.h>
  37.  
  38.  
  39.  
  40. /* the following declarations are used on PowerPC computers */
  41. #if GENERATINGCFM
  42.  
  43. pascal void SetHideOnSwitch(Boolean setValue) {
  44.     enum {
  45.     uppSetHideOnSwitch = kStackDispatchedPascalStackBased
  46.         | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(unsigned short)))
  47.         | DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char)))
  48.     };
  49.     CallUniversalProc(GetToolTrapAddress(_OSDispatch), uppSetHideOnSwitch, 0x006BL, setValue);
  50. }
  51.  
  52. pascal Boolean GetHideOnSwitch(void) {
  53.     enum {
  54.     uppGetHideOnSwitch = kStackDispatchedPascalStackBased
  55.         | RESULT_SIZE(SIZE_CODE(sizeof(unsigned char)))
  56.         | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(unsigned short)))
  57.     };
  58.     return (Boolean) CallUniversalProc(GetToolTrapAddress(_OSDispatch), uppGetHideOnSwitch, 0x006CL);
  59. }        
  60.  
  61. #endif
  62.  
  63.  
  64. /* HideCallsExist returns true if the gestaltHideLayerOnSwitchSupport
  65.     bit is set in the response returned by the gestaltOSAttr Gestalt
  66.     selector.  If this routine returns true, then it is safe to call
  67.     SetHideOnSwitch and GetHideOnSwitch. */
  68. Boolean HideCallsExist(void) {
  69.     long response;
  70.     if (Gestalt(gestaltOSAttr, &response) != noErr) response = 0;
  71.     return ((response & (1<<gestaltHideLayerOnSwitchSupport)) != 0);
  72. }
  73.  
  74.  
  75. /* IsFrontProcess returns true in *isFrontP if the process serial number
  76.     in *whichProcess refers to the front most process.  IsFrontProcess
  77.     will return an error if an error is returned by the process manager. */
  78. static OSStatus IsFrontProcess(ProcessSerialNumber *whichProcess, Boolean *isFrontP) {
  79.     ProcessSerialNumber frontPSN;
  80.     OSStatus err;
  81.         /* get the front most process */
  82.     err = GetFrontProcess(&frontPSN);    
  83.     if (err != noErr) return err;
  84.         /* check to see if it's the same as *whichProcess */
  85.     err = SameProcess(whichProcess, &frontPSN, isFrontP);
  86.     return err;
  87.     
  88. }
  89.  
  90.  
  91.  
  92. /* HideMe hides the current process making it invisible.  Calling this routine
  93.     is the same as calling the 'Hide xxxxxx' command from the application
  94.     menu in the top right corner of the screen.  HideIdleProc is a routine
  95.     of type EventIdleProc that is called by HideMe while it is waiting for the
  96.     ProcessManager to switch processes in and out of the forground, and
  97.     GetNextP is a routine of type SelectNextFrontProcess that is used by
  98.     HideMe to select the process that is to be moved into the forground
  99.     when it is hidden.  */
  100. OSStatus HideMe(EventIdleProc HideIdleProc, SelectNextFrontProcess GetNextP) {
  101.     ProcessSerialNumber myPSN, targetPSN;
  102.     Boolean isFrontP, switchFlagOn, isSamePSN;
  103.     EventRecord ev;
  104.     OSStatus err;
  105.     
  106.         /* set up locals */
  107.     switchFlagOn = false;
  108.     
  109.         /* verify we are frontmost */
  110.     err = GetCurrentProcess(&myPSN);
  111.     if (err != noErr) goto bail;
  112.     
  113.         /* verify or switch our process in front of all others */
  114.     err = IsFrontProcess(&myPSN, &isFrontP);
  115.     if (err != noErr) goto bail;
  116.     if ( ! isFrontP) {
  117.             /* if it's not the frontmost process, then switch it in */
  118.         err = SetFrontProcess(&myPSN);
  119.         if (err != noErr) goto bail;
  120.             /* wait for it to actually get switched in */
  121.         while (! isFrontP) {
  122.                 /* get the next event */
  123.             if ( ! WaitNextEvent(everyEvent, &ev,  0, NULL)) ev.what = nullEvent;
  124.                 /* pass it back to the application */
  125.             err = HideIdleProc(&ev);
  126.             if (err != noErr) goto bail;
  127.                 /* check if we're in front */
  128.             err = IsFrontProcess(&myPSN, &isFrontP);
  129.             if (err != noErr) goto bail;
  130.         }
  131.     }
  132.     
  133.         /* select the process to switch in */
  134.     err = GetNextP(&myPSN, &targetPSN);
  135.     if (err != noErr) goto bail;
  136.         /* make sure it's not the same process number as ours. */
  137.     err = SameProcess(&myPSN, &targetPSN, &isSamePSN);    
  138.     if (err != noErr) goto bail;
  139.     if (isSamePSN) { err = paramErr; goto bail; }
  140.     
  141.         /* turn on the switch and hide flag */
  142.     SetHideOnSwitch(true);
  143.     switchFlagOn = true;
  144.     
  145.         /* switch that process in */
  146.     err = SetFrontProcess(&targetPSN);
  147.     if (err != noErr) goto bail;
  148.     isFrontP = false;
  149.         /* wait for it to get switched in */
  150.     while ( ! isFrontP) {
  151.             /* get the next event */
  152.         if ( ! WaitNextEvent(everyEvent, &ev,  0, NULL)) ev.what = nullEvent;
  153.             /* pass it back to the application */
  154.         err = HideIdleProc(&ev);
  155.         if (err != noErr) goto bail;
  156.             /* check if the next process has been moved in front */
  157.         err = IsFrontProcess(&targetPSN, &isFrontP);
  158.         if (err != noErr) goto bail;
  159.     }
  160.         /* reset the flag */
  161.     SetHideOnSwitch(false);
  162.     switchFlagOn = false;
  163.         /* done */
  164.     return noErr;
  165.     
  166. bail:
  167.         /* reset the flag if we're aborting */
  168.     if (switchFlagOn) SetHideOnSwitch(false);
  169.     return err;
  170. }
  171.